package com.gframework.util;

import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.function.UnaryOperator;

import org.apache.commons.lang3.StringUtils;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;

import sun.misc.Unsafe;

/**
 * null安全的工具函数集合.
 * 
 * <p>本类的所有操作方法都不会抛出{@link NullPointerException}
 * 
 * <ul>
 * <li><strong>setIfNotNull/setIfNotEmpty {@code -} </strong>在某个值不是空时执行特定方法</li>
 * <li><strong>ifNotNull {@code -} </strong>在某个值不为空是执行操作并得到返回值</li>
 * <li><strong>nvl {@code -} </strong>如同oracle的nvl函数，如果被判断值为null则返回默认值，否则返回判断值</li>
 * <li><strong>getFirstNotEmpty {@code -} </strong>获取多个值中第一个不是空的值</li>
 * <li><strong>allIsNull/allIsEmpty {@code -} </strong>判断是否都是空</li>
 * <li><strong>handleParam {@code -} </strong>通用参数解析器，可自定义参数前后缀和处理逻辑</li>
 * <li><strong>arrayForeach {@code -} </strong>对未知类型的数组进行foreach操作</li>
 * <li><strong>getFirst {@code -} </strong>获取数组或集合的第一个值（如果有）</li>
 * <li><strong>collectionToMap/arrayToMap {@code -} </strong>集合/数组转map</li>
 * <li><strong>subList {@code -} </strong>安全的获取一个集合的子集</li>
 * <li><strong>toList {@code -} </strong>对集合/Map进一步处理并获取新的集合</li>
 * <li><strong>simpleTypeConversion {@code -} </strong>基本数据类型及其包装类以及String类型转换</li>
 * <li><strong>getEnum/getEnumIgnoreCase {@code -} </strong>获取枚举值</li>
 * <li><strong>urlEncodeUtf8/urlDecodeUtf8 {@code -} </strong>对值进行{@code utf-8}编码的url Encoding或Decoding</li>
 * 
 * <li><strong>getUnsafe {@code -} </strong>获取Unsafe类对象</li>
 * </ul>
 * 
 * @since 1.0.0
 * @author Ghwolf
 */
@SuppressWarnings("restriction")
public class GUtils {
	private GUtils(){}
	/**
	 * 空的Serializable数组
	 */
	public static final Serializable[] EMPTY_SERIALIZABLE_ARRAY = new Serializable[0];
	
	/**
	 * 取得Unsafe操作对象.
	 * 
	 * <p>此对象的操作是不安全的，请确保你能够准确的把握在进行使用。
	 * 
	 * @return sun.misc.Unsafe类对象
	 */
	public static sun.misc.Unsafe getUnsafe() {
		return UNSAFE;
	}
	
	// string/object handler

	/**
	 * null安全的执行一个setter方法.
	 * <p>如果value是null则不会执行setter方法。
	 * 
	 * @param value 要传递给setter方法的值
	 * @param setter setter方法
	 */
	public static <T> void setIfNotNull(T value,Consumer<T> setter) {
		if (value != null) {
			setter.accept(value);
		}
	}
	
	/**
	 * (null/"")安全的执行一个setter方法.
	 * <p>如果value是(null/"")则不会执行setter方法。
	 * 
	 * @param value 要传递给setter方法的值
	 * @param setter setter方法
	 */
	public static <T> void setIfNotEmpty(T value,Consumer<T> setter) {
		if (value != null && !"".equals(value)) {
			setter.accept(value);
		}
	}
	
	/**
	 * 判断一个对象，如果为null则返回null，否则调用其相关方法并返回结果。
	 * @param <T> 要判断的对象类型
	 * @param <V> 返回结果类型，任意的
	 * @param value 要判断的对象
	 * @param function 对象的方法
	 * @return 返回方法返回结果。
	 */
	public static <T,V> V ifNotNullFun(@Nullable T value,Function<T,V> function){
		return value == null ? null : function.apply(value);
	}
	
	/**
	 * 判断一个对象，如果不为null则执行相关的操作
	 * @param <T> 要判断的对象类型
	 * @param value 要判断的对象
	 * @param consumer 对象的方法
	 */
	public static <T> void ifNotNull(@Nullable T value,Consumer<T> consumer){
		if (value != null) consumer.accept(value);
	}
	
	/**
	 * 判断一个对象，如果不为null则执行相关的操作
	 * @param <T> 要判断的对象类型
	 * @param value 要判断的对象
	 * @param consumer 对象的方法
	 * @param param 消费型函数是接口接收参数，通常是setter方法参数
	 */
	public static <T,U> void ifNotNull(@Nullable T value,BiConsumer<T,U> consumer,U param){
		if (value != null) consumer.accept(value, param);
	}

	/**
	 * 如果是value是null，则返回defaultValue，否则返回value
	 * 
	 * @param value 要判断是否为null的对象
	 * @param defaultValue 默认值
	 * @return 如果value是null，返回defaultValue，否则返回value
	 */
	@Nullable
	public static <T, V extends T> T nvl(@Nullable T value, @Nullable V defaultValue) {
		return value == null ? defaultValue : value;
	}
	
	/**
	 * 传递多个值，依次进行判断，返回第一个遇到的不是null的对象，如果都是null，则返回null
	 * 
	 * @param values 要判断是否为null的对象
	 * @return 如果都是null，返回null，否则返回第一个遇到的非空对象
	 */
	@SafeVarargs
	@Nullable
	public static <T> T nvl(@Nullable T ... values) {
		if (values == null || values.length == 0) return null ;
		for (T t : values) {
			if (t != null) return t;
		}
		return null ;
	}
	
	/**
	 * 如果是value是null，则调用defaultValueSupplier获取返回结果，否则返回value
	 * 
	 * @param value 要判断是否为null的对象
	 * @param defaultValueSupplier 获取默认值的方法
	 * @return 如果是value是null，则调用defaultValueSupplier获取返回结果，否则返回value
	 */
	@Nullable
	public static <T, V extends T> T nvl(@Nullable T value, Supplier<V> defaultValueSupplier) {
		return value == null ? defaultValueSupplier.get() : value;
	}

	/**
	 * 如果是value是null，则返回defaultValue，否则返回value
	 * 
	 * @param value 要判断是否为null的对象
	 * @param defaultValue 默认值
	 * @return 如果value是null，返回defaultValue，否则返回value
	 */
	@Nullable
	public static String nvl(@Nullable String value, @Nullable String defaultValue) {
		return value == null ? defaultValue : value;
	}
	
	/**
	 * 如果是value是null，则调用defaultValueSupplier获取返回结果，否则返回value
	 * 
	 * @param value 要判断是否为null的对象
	 * @param defaultValueSupplier 获取默认值的方法
	 * @return 如果是value是null，则调用defaultValueSupplier获取返回结果，否则返回value
	 */
	@Nullable
	public static String nvl(@Nullable String value, Supplier<String> defaultValueSupplier) {
		return value == null ? defaultValueSupplier.get() : value;
	}

	/**
	 * 如果是value是null，则返回defaultValue，否则返回value
	 * 
	 * @param value 要判断是否为null的对象
	 * @param defaultValue 默认值
	 * @return 如果value是null，返回defaultValue，否则返回value
	 */
	@Nullable
	public static String nvl(@Nullable Object value, @Nullable String defaultValue) {
		return value == null ? defaultValue : value.toString();
	}

	/**
	 * 根据指定的多个字符串对象，获取第一个找到的非null且不是空字符串的字符串对象并返回，如果没有返回null。
	 * <p>如果没有任何参数，则返回null
	 * 
	 * @param strs 待获取的字符串
	 * @return 如果存在非null且非""的字符串，则返回第一个找到的，否则返回null
	 */
	@Nullable
	public static String getFirstNotEmpty(String ... strs){
		if (strs == null || strs.length == 0) return null;
		
		for (String str : strs) {
			if (str != null && str.length() != 0) {
				return str ;
			}
		}
		return null ;
	}
	
	/**
	 * 判断任意多个对象是否都是null，如果是返回true，否则返回false，如果没有传任何对象，返回false
	 * @param objs 要判断的对象，多个
	 * @return 如果都是null返回true，否则或如果没有任何对象存在，返回false
	 */
	public static boolean allIsNull(Object ... objs){
		if (objs == null || objs.length == 0) {
			return false ;
		}
		for (Object obj : objs) {
			if (obj != null) {
				return false ;
			}
		}
		return true ;
	}
	
	/**
	 * 判断任意多个对象是否都是null或""，如果是返回true，否则返回false，如果没有传任何对象，返回false
	 * @param objs 要判断的对象，多个
	 * @return 如果都是null或""返回true，否则或如果没有任何对象存在，返回false
	 */
	public static boolean allIsEmpty(Object ... objs){
		if (objs == null || objs.length == 0) {
			return false ;
		}
		for (Object obj : objs) {
			if (obj != null && !"".equals(obj)) {
				return false ;
			}
		}
		return true ;
	}
	
	/**
	 * 处理一个字符串中的参数.
	 * <p>此方法是非常灵活的，因为它可以让你自定义参数前后缀和处理方法。
	 * 
	 * @param str 要解析的参数,可以为null
	 * @param prefix 参数前缀，不能是null或""
	 * @param suffix 参数后缀，不能是null或""
	 * @param handle 每找到一个参数就执行处理操作，方法参数是参数内容（不包含前后缀），返回一个处理后的内容并替换这个参数，如果返回null，则按""处理。
	 * @return 返回处理后的参数
	 * @throws UnsupportedOperationException 如果prefix和suffix没有指定值，即为null或""
	 * @throws NullPointerException handle为null
	 */
	public static String handleParam(@Nullable String str,String prefix,String suffix,UnaryOperator<String> handle) {
		if (StringUtils.isEmpty(str)) {
			return str ;
		}
		if (StringUtils.isEmpty(prefix) || StringUtils.isEmpty(suffix)) {
			throw new UnsupportedOperationException("参数解析prefix和suffix必须是一个有意义的值，不能是null或空字符串！");
		}
		
		int prefixLength = prefix.length();
		int suffixLength = suffix.length();
		int start = 0;

		int prefixIndex = str.indexOf(prefix);
		if (prefixIndex == -1) {
			return str ;
		}
		StringBuilder sb = new StringBuilder(str.length());
		do {
			int suffixIndex = str.indexOf(suffix, prefixIndex + prefixLength);
			if (suffixIndex == -1) break;
			sb.append(str.substring(start, prefixIndex));
			// 寻找下一个字符串中的参数
			String param = str.substring(prefixIndex + prefixLength, suffixIndex);
			String paramValue = handle.apply(param);
			
			if (StringUtils.isNotEmpty(paramValue)) {
				sb.append(paramValue);
			}
			start = suffixIndex + suffixLength;
			prefixIndex = str.indexOf(prefix, start);
		} while(prefixIndex != -1);
		if (start < str.length()) {
			sb.append(str.substring(start));
		}
		return sb.toString();
	}
	
	// array handle
	
	/**
	 * 对一个可能是数组的对象进行foreach操作.
	 * <p>
	 * 由于基本数据类型的数组无法直接转换成Object[]类型，则就导致了遍历时存在的诸多问题，使用此方法可以避免这些问题。
	 * 如果array是一个数组，那么就尝试进行转换并遍历，否则不做任何处理。
	 * </p>
	 * @param array 可能的数组对象，可以为null
	 * @param call 回调函数，不能为null，第一个参数为索引号，第二个是数组值
	 */
	public static void arrayForeach(Object array,BiConsumer<Integer, Object> call) {
		if (array == null || !array.getClass().isArray()) {
			return ;
		}
		Class<?> arrayClass = array.getClass();
		if (arrayClass.getComponentType() == int.class) {
			int[] arr = (int[]) array;
			for (int x = 0 ; x < arr.length; x ++) {
				call.accept(x, arr[x]);
			}
		} else if (arrayClass.getComponentType() == double.class) {
			double[] arr = (double[]) array;
			for (int x = 0 ; x < arr.length; x ++) {
				call.accept(x, arr[x]);
			}
		} else if (arrayClass.getComponentType() == boolean.class) {
			boolean[] arr = (boolean[]) array;
			for (int x = 0 ; x < arr.length; x ++) {
				call.accept(x, arr[x]);
			}
		} else if (arrayClass.getComponentType() == byte.class) {
			byte[] arr = (byte[]) array;
			for (int x = 0 ; x < arr.length; x ++) {
				call.accept(x, arr[x]);
			}
		} else if (arrayClass.getComponentType() == char.class) {
			char[] arr = (char[]) array;
			for (int x = 0 ; x < arr.length; x ++) {
				call.accept(x, arr[x]);
			}
		} else if (arrayClass.getComponentType() == short.class) {
			short[] arr = (short[]) array;
			for (int x = 0 ; x < arr.length; x ++) {
				call.accept(x, arr[x]);
			}
		} else if (arrayClass.getComponentType() == long.class) {
			long[] arr = (long[]) array;
			for (int x = 0 ; x < arr.length; x ++) {
				call.accept(x, arr[x]);
			}
		} else if (arrayClass.getComponentType() == float.class) {
			float[] arr = (float[]) array;
			for (int x = 0 ; x < arr.length; x ++) {
				call.accept(x, arr[x]);
			}
		} else {
			Object[] arr = (Object[]) array;
			for (int x = 0 ; x < arr.length; x ++) {
				call.accept(x, arr[x]);
			}
		}
	}
	/**
	 * 对一个可能是数组的对象进行foreach操作.
	 * <p>
	 * 由于基本数据类型的数组无法直接转换成Object[]类型，则就导致了遍历时存在的诸多问题，使用此方法可以避免这些问题。
	 * 如果array是一个数组，那么就尝试进行转换并遍历，否则不做任何处理。
	 * </p>
	 * @param array 可能的数组对象，可以为null
	 * @param call 回调函数，不能为null
	 */
	public static void arrayForeach(Object array,Consumer<Object> call) {
		if (array == null || !array.getClass().isArray()) {
			return ;
		}
		Class<?> arrayClass = array.getClass();
		if (arrayClass.getComponentType() == int.class) {
			int[] arr = (int[]) array;
			for (int x = 0 ; x < arr.length; x ++) {
				call.accept(arr[x]);
			}
		} else if (arrayClass.getComponentType() == double.class) {
			double[] arr = (double[]) array;
			for (int x = 0 ; x < arr.length; x ++) {
				call.accept(arr[x]);
			}
		} else if (arrayClass.getComponentType() == boolean.class) {
			boolean[] arr = (boolean[]) array;
			for (int x = 0 ; x < arr.length; x ++) {
				call.accept(arr[x]);
			}
		} else if (arrayClass.getComponentType() == byte.class) {
			byte[] arr = (byte[]) array;
			for (int x = 0 ; x < arr.length; x ++) {
				call.accept(arr[x]);
			}
		} else if (arrayClass.getComponentType() == char.class) {
			char[] arr = (char[]) array;
			for (int x = 0 ; x < arr.length; x ++) {
				call.accept(arr[x]);
			}
		} else if (arrayClass.getComponentType() == short.class) {
			short[] arr = (short[]) array;
			for (int x = 0 ; x < arr.length; x ++) {
				call.accept(arr[x]);
			}
		} else if (arrayClass.getComponentType() == long.class) {
			long[] arr = (long[]) array;
			for (int x = 0 ; x < arr.length; x ++) {
				call.accept(arr[x]);
			}
		} else if (arrayClass.getComponentType() == float.class) {
			float[] arr = (float[]) array;
			for (int x = 0 ; x < arr.length; x ++) {
				call.accept(arr[x]);
			}
		} else {
			Object[] arr = (Object[]) array;
			for (int x = 0 ; x < arr.length; x ++) {
				call.accept(arr[x]);
			}
		}
	}
	
	
	/**
	 * 对一个数组的数据进行处理，类似于map/reduce中的map操作.
	 * <p>需要注意的是，修改操作会直接在原数组上实现
	 * @param arr 要处理的数组，如果为null或长度为0则不作任何事情
	 * @param mapFunction 处理函数
	 * @throws NullPointerException 如果mapFunction为null
	 */
	public static <T> void map(@Nullable T[] arr,UnaryOperator<T> mapFunction){
		if (arr == null || arr.length == 0) return ;
		for (int x = 0 ; x < arr.length ; x ++) {
			arr[x] = mapFunction.apply(arr[x]);
		}
	}
	
	/**
	 * 取得一个集合的第一个元素，如果元素为null，或不存在第一个元素，则返回null，否则返回第一个元素。
	 * @param list 要获取的元素
	 * @return 返回第一个元素，如果没有返回null
	 */
	@Nullable
	public static <T> T getFirst(@Nullable List<T> list) {
		return list == null || list.isEmpty() ? null : list.get(0);
	}
	
	/**
	 * 取得一个数组的第一个元素，如果元素为null，或不存在第一个元素，则返回null，否则返回第一个元素。
	 * @param array 要获取的元素
	 * @return 返回第一个元素，如果没有返回null
	 */
	@Nullable
	public static <T> T getFirst(@Nullable T[] array) {
		return array == null || array.length == 0 ? null : array[0];
	}
	
	/**
	 * 将一个集合转换为map，map的key来源于集合中每一个对象特定的属性，这个key的获取需要通过getKey函数式接口设置.
	 * <p><strong>如果getKey方法获取的key值为null，则会忽略对应对象，不放到map中。</strong>
	 * @param collection 要转换的集合，如果为null则集合长度为0
	 * @param getKey 获取key的操作方法，不能为null
	 * @return 返回Map集合，如果没有数据，集合长度为0
	 * @throws NullPointerException 如果getKey为null
	 */
	public static <T,K> Map<K,T> collectionToMap(@Nullable Collection<T> collection,Function<T, K> getKey) {
		return collectionToMap(collection,getKey,v->v);
	}
	
	/**
	 * 将一个数组转换为map，map的key来源于数组中每一个对象特定的属性，这个key的获取需要通过getKey函数式接口设置.
	 * <p><strong>如果getKey方法获取的key值为null，则会忽略对应对象，不放到map中。</strong>
	 * @param array 要转换的数组，如果为null则集合长度为0
	 * @param getKey 获取key的操作方法，不能为null
	 * @return 返回Map集合，如果没有数据，集合长度为0
	 * @throws NullPointerException 如果getKey为null
	 */
	public static <T,K> Map<K,T> arrayToMap(@Nullable T[] array,Function<T, K> getKey) {
		return arrayToMap(array,getKey,v->v);
	}
	
	/**
	 * 将一个集合转换为map，map的key来源于集合中每一个对象特定的属性，这个key和value的获取需要通过函数式接口设置.
	 * <p><strong>如果getKey方法获取的key值为null，则会忽略对应对象，不放到map中。</strong>
	 * @param collection 要转换的集合，如果为null则集合长度为0
	 * @param getKey 获取key的操作方法，不能为null
	 * @param getValue 获取value的操作方法，不能为null
	 * @return 返回Map集合，如果没有数据，集合长度为0
	 * @throws NullPointerException 如果getKey或getValue为null
	 */
	public static <T,K,V> Map<K,V> collectionToMap(@Nullable Collection<T> collection,Function<T, K> getKey,Function<T, V> getValue) {
		if (collection == null || collection.isEmpty()) return Collections.emptyMap();
		Map<K,V> map = new HashMap<>(collection.size());
		for (T t : collection) {
			K k = getKey.apply(t);
			if (k != null) {
				map.put(k,getValue.apply(t));
			}
		}
		return map ;
	}
	
	/**
	 * 将一个数组转换为map，map的key来源于数组中每一个对象特定的属性，这个key和value的获取需要通过函数式接口设置.
	 * <p><strong>如果getKey方法获取的key值为null，则会忽略对应对象，不放到map中。</strong>
	 * @param array 要转换的集合，如果为null则集合长度为0
	 * @param getKey 获取key的操作方法，不能为null
	 * @param getValue 获取value的操作方法，不能为null
	 * @return 返回Map集合，如果没有数据，集合长度为0
	 * @throws NullPointerException 如果getKey或getValue为null
	 */
	public static <T,K,V> Map<K,V> arrayToMap(@Nullable T[] array,Function<T, K> getKey,Function<T, V> getValue) {
		if (array == null || array.length == 0) return Collections.emptyMap();
		Map<K,V> map = new HashMap<>(array.length);
		for (T t : array) {
			K k = getKey.apply(t);
			if (k != null) {
				map.put(k,getValue.apply(t));
			}
		}
		return map ;
	}
	
	/**
	 * 安全的截断一个List集合，截断范围[start,end).
	 * <p>如果list为空或范围超出，则返回空的集合，超出范围部分则会忽视。
	 * @param list 要截断的集合，可以为null
	 * @param start 开始索引（包含）
	 * @param end 结束索引（不包含）
	 * @return 返回截断后的集合，如果不存在数据，则集合长度为0
	 */
	public static <T> List<T> subList(@Nullable List<T> list,int start,int end){
		if (list == null || list.isEmpty() || start > end || start >= list.size()) {
			return Collections.emptyList();
		}
		if (start < 0) start = 0 ;
		if (end > list.size()) end = list.size();
		return list.subList(start, end);
	}

	/**
	 * 本方法会将一个集合转换为集合
	 * @param list 要转换的list集合，可以为空，为空则返回一个长度为0的数组
	 * @param handleValue 针对集合每个对象的处理方法
	 * @return 返回转换后的集合，如果没有数据，则集合长度为0
	 * @throws NullPointerException 如果handleValue或arrType为空
	 */
	public static <T,R> List<R> toList(@Nullable Collection<T> list,Function<T, R> handleValue) {
		if (list == null || list.isEmpty()) {
			return Collections.emptyList();
		} else {
			List<R> arr = new ArrayList<>(list.size());
			for (T t : list) {
				arr.add(handleValue.apply(t));
			}
			return arr ;
		}
	}
	
	// map handle
	
	/**
	 * 本方法可以将一个map集合转换为数组
	 * @param <K> map key类型
	 * @param <V> map value类型
	 * @param <R> 数组存储对象类型
	 * @param map 要转换的map对象，可以为null
	 * @param createBean bean创建操作，会将map的key与value传入，不能为null
	 * @return 返回新的对象集合，如果没有则集合长度为0
	 */
	public static <K,V,R> List<R> toList(@Nullable Map<K,V> map,BiFunction<K, V, R> createBean) {
		if (map == null || map.isEmpty()) {
			return Collections.emptyList();
		} else {
			List<R> list = new ArrayList<>(map.size());
			map.forEach((k,v)->list.add(createBean.apply(k, v)));
			return list ;
		}
	}
	
	// type handle
	
	/**
	 * 本方法负责对基本的那些数据类型提供简单的类型转换操作.
	 * <p>由于Byte、Integer、Double、String等这些包装类和String类等一些Number的子类之间无法直接转换，但是却存在逻辑上的转换操作，
	 * 因此各个地方手动转换非常的复杂。因此才会产生此方法以简化这类操作。
	 * 
	 * <p>通常此方法应当和反射操作是绑定的，因此返回结果依然是Object，而且如果无法转换，则会返回obj原始对象。
	 * 
	 * <p>此方法目前支持转换的类型有：Byte、Short、Character、Integer、Boolean、
	 * Long、BigDecimal、BigInteger、Float、Double、String。以及相关类型的原始数据类型。
	 * <p>其中对于String类型来说，除了null值外，任何类型转换为string都是调用其toString方法完成的。
	 * <p>而对于Boolean类型来说，整数0、null、""、布尔值false都会当作false处理。
	 * 
	 * @param obj 要转换的对象
	 * @param type 要转换的类型
	 * @return 如果转换成功，则返回转换后的对象，否则返回原始对象，如果参数为null，则返回obj
	 */
	public static Object simpleTypeConversion(@Nullable Object obj,@Nullable Class<?> type) {
		if (obj == null || type == null) {
			return type == boolean.class || type == Boolean.class ? Boolean.FALSE : obj ;
		}
		if (ClassUtils.isAssignable(type, obj.getClass())) {
			return obj ;
		}
		if (type == String.class) {
			return obj.toString();
		} else if (type == Boolean.class || type == Boolean.TYPE) {
			if (obj instanceof Number) {
				return ((Number) obj).intValue() != 0;
			} else {
				return !"".equals(obj);
			}
		} else if (type == Character.class || type == Character.TYPE) {
			if (obj instanceof Number) {
				return (char)((Number) obj).intValue();
			} else {
				return obj ;
			}
		} else if (Number.class.isAssignableFrom(obj.getClass()) && (type.isPrimitive() || Number.class.isAssignableFrom(type))) {
			if (type == Integer.class || type == Integer.TYPE) {
				return ((Number)obj).intValue();
			} else if (type == Double.class || type == Double.TYPE) {
				return ((Number)obj).doubleValue();
			} else if (type == Long.class || type == Long.TYPE) {
				return ((Number)obj).longValue();
			} else if (type == Byte.class || type == Byte.TYPE) {
				return ((Number)obj).byteValue();
			} else if (type == BigDecimal.class) {
				return BigDecimal.valueOf(((Number)obj).doubleValue());
			} else if (type == BigInteger.class) {
				return BigInteger.valueOf(((Number)obj).longValue());
			} else if (type == Short.class || type == Short.TYPE) {
				return ((Number)obj).shortValue();
			} else if (type == Float.class || type == Float.TYPE) {
				return ((Number)obj).floatValue();
			}
		}
		return obj;
	}
	
	
	// other
	
	/**
	 * 不区分大小写的根据名称获取枚举对象
	 * @param enumClass 枚举类型
	 * @param name 要获取的枚举名称，如果为null则返回null
	 * @return 如果存在则返回否则返回null
	 */
	@Nullable
	public static <T extends Enum<T>> T getEnumIgnoreCase(Class<T> enumClass,@Nullable String name) {
		if (StringUtils.isEmpty(name)) return null ;
		
		for (T e : enumClass.getEnumConstants()) {
			if (e.name().equalsIgnoreCase(name)) {
				return e;
			}
		}
		return null ;
	}
	
	/**
	 * 区分大小写的根据名称获取枚举对象
	 * @param enumClass 枚举类型
	 * @param name 要获取的枚举名称，如果为null则返回null
	 * @return 如果存在则返回否则返回null
	 */
	@Nullable
	public static <T extends Enum<T>> T getEnum(Class<T> enumClass,@Nullable String name) {
		if (StringUtils.isEmpty(name)) return null ;
		
		for (T e : enumClass.getEnumConstants()) {
			if (e.name().equals(name)) {
				return e;
			}
		}
		return null ;
	}

	
	
	/**
	 * 对字符串进行utf-8的url编码处理
	 * 本方法是为了处理URLEncoder每次都要进行无意义的异常捕捉，且默认编码不是utf-8而产生的。
	 * 
	 * @param str 要处理的字符串，可以为空
	 * @return 返回处理后的字符串，可能为空
	 */
	@Nullable
	public static String urlEncodeUtf8(@Nullable String str) {
		if (StringUtils.isEmpty(str)) {
			return str ;
		}
		try {
			return URLEncoder.encode(str, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			throw new UnsupportedOperationException(e);
		}
	}
	/**
	 * 对字符串进行utf-8的url解码处理
	 * 本方法是为了处理URLDecoder每次都要进行无意义的异常捕捉，且默认编码不是utf-8而产生的。
	 * 
	 * @param str 要处理的字符串，可以为空
	 * @return 返回处理后的字符串，可能为空
	 */
	@Nullable
	public static String urlDecodeUtf8(@Nullable String str) {
		if (StringUtils.isEmpty(str)) {
			return str ;
		}
		try {
			return URLDecoder.decode(str, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			throw new UnsupportedOperationException(e);
		}
	}

	
	private static final sun.misc.Unsafe UNSAFE;
	static {
		Field unsafe;
		try {
			unsafe = Class.forName("sun.misc.Unsafe").getDeclaredField("theUnsafe");
			unsafe.setAccessible(true);
			UNSAFE = (Unsafe) unsafe.get(null);
		} catch (Exception e) {
			throw new Error("当前JDK版本【" + System.getProperty("java.version") + "】不支持通过theUnsafe属性获取Unsafe类对象！",e);
		}
	}

}
